home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
- Amsterdam, The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior permission.
-
- STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
-
- #include "Python.h"
- #include "import.h"
-
- /*
- ** An Order-8 ordered dithering matrix. Taken from netpbm, which in
- ** turn has it from "Digital Halftoning" by Robert Ulichney, MIT
- ** Press, ISBN 0-262-21009-6.
- */
-
- static int dither8[16][16] = {
- 1,235, 59,219, 15,231, 55,215, 2,232, 56,216, 12,228, 52,212,
- 129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116,
- 33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244,
- 161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92,
- 9,225, 49,209, 5,239, 63,223, 10,226, 50,210, 6,236, 60,220,
- 137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124,
- 41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252,
- 169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86,
- 3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214,
- 131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118,
- 35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246,
- 163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94,
- 11,227, 51,211, 7,237, 61,221, 8,224, 48,208, 4,238, 62,222,
- 139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126,
- 43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254,
- 171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 };
-
- static PyObject *errobject;
-
- static PyObject *format_grey, *format_xgrey, *format_bitmap;
-
- /*
- ** Get the relevant info from a format object:
- ** pixel size and alignment and bitpositions and masks for
- ** each component.
- */
- static int
- getfmtinfo(fmt, size, align, mr, mg, mb, sr, sg, sb)
- PyObject *fmt;
- int *size, *align, *mr, *mg, *mb, *sr, *sg, *sb;
- {
- PyObject *dict, *value;
- int ma, sa;
-
- if ( (dict=PyObject_GetAttrString(fmt, "descr")) == NULL )
- return 0;
-
- if ( (value=PyDict_GetItemString(dict, "size")) == NULL )
- return 0;
- if ( (*size=PyInt_AsLong(value)) == -1 )
- return 0;
- if ( *size != 8 && *size != 16 && *size != 32 )
- return 0;
- *size /= 8;
-
- if ( (value=PyDict_GetItemString(dict, "align")) == NULL )
- return 0;
- if ( (*align=PyInt_AsLong(value)) == -1 )
- return 0;
- if ( *align != 8 && *align != 16 && *align != 32 )
- return 0;
- *align /= 8;
-
- if ( (value=PyDict_GetItemString(dict, "comp")) == NULL )
- return 0;
- *mr = *mg = *mb = *sr = *sg = *sb = ma = sa = 0;
- if ( !PyArg_ParseTuple(value, "(ii)|(ii)(ii)(ii)",
- sr, mr, sg, mg, sb, mb, &sa, &ma) )
- return 0;
- *mr = (1<<*mr) - 1;
- *mg = (1<<*mg) - 1;
- *mb = (1<<*mb) - 1;
-
- Py_DECREF(dict);
- return 1;
- }
-
- static char doc_shuffle[] =
- "Re-arrange component bits in pixels.\n"
- "Args: (data, width, height, source_format, result_format)\n"
- "Returns: string containing shuffled pixel data";
-
- static PyObject *
- imo_shuffle(self, args)
- PyObject *self;
- PyObject *args;
- {
- PyObject *srcfmt, *dstfmt;
- unsigned char *srcp8, *dstp8;
- unsigned short *srcp16, *dstp16;
- unsigned long *srcp32, *dstp32;
- unsigned long srcpixel, dstpixel, comp;
- int srcalign, dstalign;
- int srcsize, dstsize;
- int smr, smg, smb, ssr, ssg, ssb, dmr, dmg, dmb, dsr, dsg, dsb;
- PyObject *rv;
- int w, rowlen, h, size, x, y;
-
- if (!PyArg_ParseTuple(args, "s#iiOO", &srcp8, &size, &w, &h,
- &srcfmt, &dstfmt))
- return NULL;
-
- /*
- ** Get the relevant info from the format objects, do some argument
- ** checking and allocate the result buffer.
- */
- if (!getfmtinfo(srcfmt, &srcsize, &srcalign, &smr, &smg, &smb,
- &ssr, &ssg, &ssb) ||
- !getfmtinfo(dstfmt, &dstsize, &dstalign, &dmr, &dmg,
- &dmb, &dsr, &dsg, &dsb) ) {
- PyErr_SetString(errobject, "Invalid format-object");
- return NULL;
- }
- rowlen = (w*srcsize+srcalign-1) & ~(srcalign-1);
- if ( rowlen*h != size ) {
- PyErr_SetString(errobject, "Incorrectly sized data");
- return NULL;
- }
-
- rowlen = (w*dstsize+dstalign-1) & ~(dstalign-1);
- if ( (rv=PyString_FromStringAndSize((char *)0, rowlen*h)) == 0 )
- return NULL;
- dstp8 = (unsigned char *)PyString_AsString(rv);
-
- dstp16 = (unsigned short *)dstp8;
- dstp32 = (unsigned long *)dstp8;
- srcp16 = (unsigned short *)srcp8;
- srcp32 = (unsigned long *)srcp8;
-
- for( y=0; y<h; y++) {
- for( x=0; x<w; x++ ) {
-
- /* Get the source pixel into srcpixel */
- if ( srcsize==1 ) srcpixel = *srcp8++; else
- if ( srcsize==2 ) srcpixel = *srcp16++; else
- srcpixel = *srcp32++;
-
- dstpixel = 0;
-
- /* For each existing (and wanted) component,
- **grab/scale/insert it
- */
- if ( smr && dmr ) {
- comp = (srcpixel >> ssr) & smr; /* Get bits */
- comp = (comp*dmr)/smr; /* convert magnitude */
- dstpixel = dstpixel | (comp<<dsr); /* Insert */
- }
- if ( smg && dmg ) {
- comp = (srcpixel >> ssg) & smg;
- comp = (comp*dmg)/smg;
- dstpixel = dstpixel | (comp << dsg);
- }
- if ( smb && dmb ) {
- comp = (srcpixel >> ssb) & smb;
- comp = (comp*dmb)/smb;
- dstpixel = dstpixel | (comp << dsb);
- }
-
- /* And put the result in the output buffer,
- **in the correct size
- */
- if ( dstsize==1 ) *dstp8++ = dstpixel; else
- if ( dstsize==2 ) *dstp16++ = dstpixel; else
- *dstp32++ = dstpixel;
- }
- /* Finally, do end-of-row alignment. Note that this code works
- ** because we have checked that size and align are 1, 2 or 4,
- ** nothing else.
- */
- if ( srcalign > srcsize ) {
- if ( srcsize==1 )
- while( (long)srcp8 & (srcalign-1) ) srcp8++;
- else if ( srcsize==2 )
- while( (long)srcp16 & (srcalign-1) ) srcp16++;
- else
- while( (long)srcp32 & (srcalign-1) ) srcp32++;
- }
- if ( dstalign > dstsize ) {
- if ( dstsize==1 )
- while( (long)dstp8 & (dstalign-1) )
- *dstp8++ = 0;
- else if ( srcsize==2 )
- while( (long)dstp16 & (dstalign-1) )
- *dstp16++ = 0;
- else
- while( (long)dstp32 & (dstalign-1) )
- *dstp32++ = 0;
- }
- }
- return rv;
- }
-
- static char doc_dither[] =
- "Dither greyscale to bitmap using an order-8 ordered dither.\n"
- "Args: (data, width, height, source_format, result_format)\n"
- "Returns: string containing bitmap data";
-
- static PyObject *
- imo_dither(self, args)
- PyObject *self;
- PyObject *args;
- {
- PyObject *srcfmt, *dstfmt;
- PyObject *rv;
- unsigned char *srcdata, *dstdata;
- int x, y, h, w, rowlen, size;
-
- #define _SRC(x, y) (srcdata[((y)*rowlen)+(x)])
- #define _DST(x, y) (dstdata[((y)*w)+(x)])
-
-
- if ( !PyArg_ParseTuple(args, "s#iiOO", &srcdata, &size, &w, &h,
- &srcfmt, &dstfmt) )
- return NULL;
- if ( (srcfmt != format_xgrey && srcfmt != format_grey) ||
- dstfmt != format_bitmap ) {
- PyErr_SetString(errobject,
- "Only supporting (x)grey to pbmbitmap currently");
- return NULL;
- }
-
- if (srcfmt == format_grey )
- rowlen = (w+3) & ~3;
- else
- rowlen = w;
- if ( size != rowlen*h ) {
- PyErr_SetString(errobject, "Incorrect data size");
- return NULL;
- }
- if( (rv=PyString_FromStringAndSize((char *)0, w*h)) == NULL )
- return NULL;
- dstdata = (unsigned char *)PyString_AsString(rv);
- for(y=0; y<w; y++)
- for(x=0; x<h; x++)
- if ( _SRC(x, y) >= dither8[y&0xf][x&0xf] )
- _DST(x, y) = 1;
- else
- _DST(x, y) = 0;
- return rv;
- }
-
- /* List of functions defined in the module */
-
- static struct PyMethodDef xxx_module_methods[] = {
- {"shuffle", imo_shuffle, 1, doc_shuffle},
- {"dither", imo_dither, 1, doc_dither},
- {NULL, NULL} /* sentinel */
- };
-
-
- /* Initialization function for the module (*must* be called initimgxxx) */
- static char doc_imgop[] = "Various operations on images";
-
- void
- initimgop()
- {
- PyObject *m, *d, *x, *formatmodule, *formatdict;
-
- /* Create the module and add the functions */
- m = Py_InitModule("imgop", xxx_module_methods);
-
- /* Add some symbolic constants to the module */
- d = PyModule_GetDict(m);
- errobject = PyString_FromString("imgop.error");
- PyDict_SetItemString(d, "error", errobject);
- x = PyString_FromString(doc_imgop);
- PyDict_SetItemString(d, "__doc__", x);
-
- /* Get supported formats */
- if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
- Py_FatalError("imgxxx depends on imgformat");
- if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
- Py_FatalError("imgformat has no dict");
-
- format_grey = PyDict_GetItemString(formatdict,"grey");
- format_xgrey = PyDict_GetItemString(formatdict,"xgrey");
- format_bitmap = PyDict_GetItemString(formatdict,"pbmbitmap");
-
- /* Check for errors */
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module imgop");
- }
-